﻿#include <QApplication>
#include <QtXml>
#include <iostream>

// ReVo ne povas uzi kiel fonto de prefiksoj kaj sufiksoj, cxar partoj de vortoj ne havas limoj.

// Agordoj por dosieron strukturon
const bool writeRoots = true;
const bool writeDerivs = false;
const bool spaceBeforeRoot = false;
const bool showWordDelimiters = true;
const bool onlyOneWordPerLine = false;

// UTF8 aux ISO8859-3 dosiero signaro.
// Vortaro havas ne latin1 leteroj, (vidu "sigma-algebro") gxi anstatauxigxos de '?'
const bool useUnicode = true;

size_t maxRootsCount = -1;  // limigi radix kiomo, por sencimigo

#define REVO_PATH "E:/sendoj/eogram/revo"

QList<QString> roots;

QList<QString> pureRoots; // без окончаний, ekzemple adverboj

QMap<QString, QString> literojKodoj;

void readLiteroj()
{
  QDomDocument doc("mydocument");
  QFile file(REVO_PATH "/cfg/literoj.xml");
  if (!file.open(QIODevice::ReadOnly))
      return;
  if (!doc.setContent(&file)) {
      file.close();
      return;
  }
  file.close();

  QDomElement docElem = doc.documentElement();

  QDomNodeList list = docElem.elementsByTagName("l");
  for (int i=0; i<list.count(); i++)
  {
    QDomNode &node = list.at(i);
    QDomNamedNodeMap &attrs = node.attributes();
    Q_ASSERT(attrs.contains("nomo") && attrs.contains("kodo"));

    QString nomo = attrs.namedItem("nomo").nodeValue();
    QString kodo = attrs.namedItem("kodo").nodeValue();
    literojKodoj.insert(nomo, kodo);
  }
}


void preprocessFile(QString &txt)
{
  for (auto it = literojKodoj.begin(); it!=literojKodoj.end(); ++it)
  {
    txt.replace("&" + it.key() + ";", "&" + it.value() + ";");
  }
}

void addToResult(QString &result, const QString &part)
{
  if (result.isEmpty())
    result = part;
  else
  {
    if (result[result.count()-1] == '/' || result[result.count()-1] == ',')
      result = result + part;
    else
      result = result + "/" + part;
  }
}

// kombadas de la frukton
QString postprocessVorto(const QString &txt)
{
  QString res = txt;
  if (!showWordDelimiters)
    res.replace("/", "");

  for (;;)
  {
    int len = res.length();
    res.replace("\n", " ");
    res.replace("  ", " ");
    res.replace(", ", ",");
    res.replace(" ,", ",");
    if (len == res.length())
      break;
  }

  if (onlyOneWordPerLine)
    res.replace(",", "\n");
  else
    res.replace(",", ", ");

  return res;
}


QString readKap(const QDomElement & e, QString &root)
{
  Q_ASSERT(!e.isNull());
  Q_ASSERT(e.nodeName() == "kap");

  QString result;
  for (QDomNode n = e.firstChild(); !n.isNull(); n=n.nextSibling())
  {
    if (n.nodeName() == "rad")
    {
      root = n.toElement().text().trimmed();
      addToResult(result, root);
    }

    else if (n.nodeName() == "tld")
      addToResult(result, root);

    else if (n.nodeName() == "#text")
      addToResult(result, n.nodeValue().trimmed());

    else if (n.nodeName() == "var")
    {
      for (QDomNode invar = n.firstChild(); !invar.isNull(); invar=invar.nextSibling())
        if (invar.nodeName() == "kap")
          result += readKap(invar.toElement(), root);
    }
  }
  return result;
}

void saveList(QList<QString> &vortolisto, const QString &fileName)
{
  // удаление дубликатов и пересоритровка
  QSet<QString> set = QSet<QString>::fromList(vortolisto);
  vortolisto.clear();
  vortolisto = QList<QString>::fromSet(set);
//  qSort(vortolisto.begin(), vortolisto.end());
//  qSort(vortolisto.begin(), vortolisto.end(), [](const QString &s1, const QString &s2) { return s1.compare(s2, Qt::CaseInsensitive) < 0; });
  // сортировка не работает

  QFile file(fileName);
  if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
  {
    Q_ASSERT(false);
    return;
  }

  QTextStream outFile(&file);
  outFile.setCodec(useUnicode ? "UTF-8" : "Latin3");

  for (auto it = vortolisto.begin(); it != vortolisto.end(); ++it)
  {
    outFile << *it << endl;
  }
}

bool scanFile(const QString &fileName, QTextStream &outFile)
{
   QFile file(fileName);

   if (!file.open(QIODevice::ReadOnly))
       return false;

   QByteArray fbytes = file.readAll();
   QString fcont = QString::fromLocal8Bit(fbytes.data(), fbytes.count()); // todo use latin1
   file.close();

   preprocessFile(fcont);

   QDomDocument doc("mydocument");
   if (!doc.setContent(fcont))
       return false;


   QDomElement docElem = doc.documentElement();
   docElem = docElem.namedItem("art").toElement();
   Q_ASSERT(!docElem.isNull());


   QDomNode n = docElem.firstChild();
   QString root;
   while (!n.isNull())
   {
       QDomElement e = n.toElement(); // try to convert the node to an element.
       if (!e.isNull())
       {

         if (e.tagName() == "kap")
         {
           if (spaceBeforeRoot)
             outFile << endl;
           if (writeRoots)
           {
             QString &txt = readKap(e, root);
             if (txt[0] == '-' || txt[txt.length()-1] == '-' || txt.trimmed().count(' ')) // todo исключить слова начинающиеся с большой буквы
             {
               // estas parto de vorto au ne unu vorto sed multo
             }
             else
             {
//               Q_ASSERT(txt.count('/') <= 2);
               int i = txt.indexOf('/');
               if (i >= 0)
               {
                 Q_ASSERT(i);
                 txt = txt.left(i); // forigi chio post '/'
                 roots << postprocessVorto(txt);
               }
               else
               {
                 pureRoots << postprocessVorto(txt);
               }
             }
           }
           readKap(e, root);
         }

         else if (e.tagName() == "drv")
         {
            if (writeDerivs)
            {
              QDomElement kap = e.namedItem("kap").toElement();
              Q_ASSERT(!kap.isNull());
              outFile << postprocessVorto(readKap(kap, root));

              //под тегом drv: <gra><vspec>ekkrio</vspec></gra>  
              QDomElement gra = e.namedItem("gra").toElement();
              Q_ASSERT(!gra.isNull());
              outFile << "\t\t" << gra.text() << endl;

              outFile << endl;
         }
       }
       n = n.nextSibling();
   }

   return true;
}

int main(int argc, char *argv[])
{
  readLiteroj();

  QFile file(REVO_PATH "/out.txt");
  if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    return -1;

  QTextStream outFile(&file);
  outFile.setCodec(useUnicode ? "UTF-8" : "Latin3");

  QDirIterator it(REVO_PATH "/xml/");
  while (it.hasNext() && --maxRootsCount)
  {
    const QString &fileName = it.next();
    const QFileInfo fi(fileName);
    if (QString("xml").compare("XML", fi.suffix(), Qt::CaseInsensitive) == 0)
    {
       scanFile(fileName, outFile);
    }
  }

  if (writeRoots)
  {
    saveList(roots, REVO_PATH "/roots.txt");
    saveList(pureRoots, REVO_PATH "/pureRoots.txt");
  }
 }